package com.ymt.bpm.service.mobile;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ymt.bpm.dao.MDao;
import com.ymt.bpm.dao.Mapper;
import com.ymt.bpm.engine.EngineConst;
import com.ymt.bpm.model.*;
import com.ymt.bpm.service.engine.bpd.BpdVersionCacheService;
import com.ymt.bpm.util.AES;
import com.ymt.bpm.util.Const;
import com.ymt.bpm.util.DateUtil;
import com.ymt.bpm.util.DhxUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Johnny on 2017/11/7.
 */
@Service
public class MTaskService {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private MDao dao;

    @Autowired
    private BpdVersionCacheService bvcs;

    public JSONObject getTodo(String tenantId, String tiId, int timezoneOffset) {
        JSONObject rtn = new JSONObject();
        PTaskTodo todo = new PTaskTodo();
        if (tenantId!=null && StringUtils.isNumeric(tenantId)) {
            todo.setTenantId(Integer.parseInt(tenantId));
        }
        todo.setTiId(tiId);
        todo.setReceiveTime(DateUtil.getGMTDate());
        todo.setStatus(PTaskTodo.STATUS_READ);
        todo = dao.selectOne(Mapper.PTaskTodoMapper, "selectByPrimaryKey", todo);
        PPi pi = dao.selectOne(Mapper.PPiMapper, "selectByPrimaryKey", todo.getPiEid());
        JSONObject tijo = new JSONObject();
        //tijo.put("tiId", AES.encrypt(todo.getTiId()));
        tijo.put("activityName", todo.getActivityName());
        tijo.put("priority", todo.getPriority());
        tijo.put("createTime", DateUtil.formatDate(todo.getCreateTime(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
        tijo.put("receiveTime", DateUtil.formatDate(todo.getReceiveTime(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
        tijo.put("dueTime", DateUtil.formatDate(todo.getDueTime(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
        rtn.put("ti", tijo);
        JSONObject pijo = new JSONObject();
        pijo.put("piEid", AES.encrypt(pi.getPiEid()));
        pijo.put("piId", AES.encrypt(pi.getPiId()));
        pijo.put("bpdId", pi.getBpdId());
        pijo.put("versionid", pi.getVersionid());
        pijo.put("status", pi.getStatus());
        pijo.put("title", pi.getTitle());
        pijo.put("bizNo", pi.getBizNo());
        pijo.put("bpdName", pi.getBpdName());
        pijo.put("createTime", DateUtil.formatDate(pi.getCreateTime(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
        pijo.put("dueTime", DateUtil.formatDate(pi.getDueTime(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
        pijo.put("creatorName", pi.getUserName());
        rtn.put("pi", pijo);

        //查询version
        JSONObject version = bvcs.getVersionJson(tenantId, pi.getBpdId(), pi.getVersionid());
        version.remove(EngineConst.BPMN);   //remove bpmn for performance issue
        //activityConf
        JSONObject activityConf = version.getJSONObject("bpmnConfig")
                .getJSONObject(todo.getActivityId());
        //form
        JSONObject formBinding = activityConf.getJSONObject("formBinding");
        rtn.put("formBinding", formBinding);
        rtn.put("activityConf", activityConf);

        //data in main table
        rtn.put("datam", getDataM(tenantId, todo.getPiEid()));

        return rtn;
    }

    public JSONObject getDone(String tenantId, String tiId, int timezoneOffset) {
        JSONObject rtn = new JSONObject();
        PTaskDone done = dao.selectOne(Mapper.PTaskDoneMapper, "selectByPrimaryKey", tiId);
        JSONObject tijo = new JSONObject();
        //tijo.put("tiId", done.getTiId());
        tijo.put("activityName", done.getActivityName());
        tijo.put("priority", done.getPriority());
        tijo.put("createTime", DateUtil.formatDate(done.getCreateTime(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
        tijo.put("receiveTime", DateUtil.formatDate(done.getReceiveTime(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
        tijo.put("dueTime", DateUtil.formatDate(done.getDueTime(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
        tijo.put("completeDate", DateUtil.formatDate(done.getCompleteDate(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
        rtn.put("ti", tijo);
        JSONObject pijo = new JSONObject();
        String bpdId = null;
        int versionId = 0;
        PPi pi = dao.selectOne(Mapper.PPiMapper, "selectByPrimaryKey", done.getPiEid());
        if (pi!=null) {
            bpdId = pi.getBpdId();
            versionId = pi.getVersionid();
            pijo.put("piEid", AES.encrypt(pi.getPiEid()));
            pijo.put("piId", AES.encrypt(pi.getPiId()));
            pijo.put("bpdId", pi.getBpdId());
            pijo.put("versionid", pi.getVersionid());
            pijo.put("status", pi.getStatus());
            pijo.put("title", pi.getTitle());
            pijo.put("bizNo", pi.getBizNo());
            pijo.put("bpdName", pi.getBpdName());
            pijo.put("createTime", DateUtil.formatDate(pi.getCreateTime(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
            pijo.put("dueTime", DateUtil.formatDate(pi.getDueTime(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
        } else {
            PPiHi hi = dao.selectOne(Mapper.PPiHiMapper, "selectByPrimaryKey", done.getPiEid());
            bpdId = hi.getBpdId();
            versionId = hi.getVersionid();
            pijo.put("piEid", AES.encrypt(hi.getPiEid()));
            pijo.put("piId", AES.encrypt(hi.getPiId()));
            pijo.put("bpdId", hi.getBpdId());
            pijo.put("versionid", hi.getVersionid());
            pijo.put("status", hi.getStatus());
            pijo.put("title", hi.getTitle());
            pijo.put("bizNo", hi.getBizNo());
            pijo.put("bpdName", hi.getBpdName());
            pijo.put("createTime", DateUtil.formatDate(hi.getCreateTime(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
            pijo.put("dueTime", DateUtil.formatDate(hi.getDueTime(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
            pijo.put("completeDate", DateUtil.formatDate(hi.getCompleteDate(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
        }
        rtn.put("pi", pijo);

        //查询version
        JSONObject version = bvcs.getVersionJson(tenantId, bpdId, versionId);
        version.remove(EngineConst.BPMN);   //remove bpmn for performance issue
        //activityConf
        JSONObject activityConf = version.getJSONObject("bpmnConfig")
                .getJSONObject(done.getActivityId());
        //form
        JSONObject formBinding = activityConf.getJSONObject("formBinding");
        rtn.put("formBinding", formBinding);
        rtn.put("activityConf", activityConf);

        //data in main table
        rtn.put("datam", getDataM(tenantId, done.getPiEid()));

        return rtn;
    }

    public JSONObject getAppl(String tenantId, String piEid, String status, int timezoneOffset) {
        JSONObject rtn = new JSONObject();
        JSONObject pijo = new JSONObject();
        String bpdId = null;
        int versionId = 0;
        Map<String, Object> paramMap = new HashMap<String, Object>();
        if (tenantId!=null && StringUtils.isNumeric(tenantId)) {
            paramMap.put(Const.TENANT_ID, tenantId);
        }
        if (PPiHi.STATUS_TERMINATED.equals(status) || PPiHi.STATUS_COMPLETE.equals(status)
                || PPiHi.STATUS_DELETED.equals(status)) {
            PPiHi hi = dao.selectOne(Mapper.PPiHiMapper, "selectByPrimaryKey", piEid);
            bpdId = hi.getBpdId();
            versionId = hi.getVersionid();
            pijo.put("piEid", AES.encrypt(hi.getPiEid()));
            pijo.put("piId", AES.encrypt(hi.getPiId()));
            pijo.put("bpdId", hi.getBpdId());
            pijo.put("versionid", hi.getVersionid());
            pijo.put("status", hi.getStatus());
            pijo.put("title", hi.getTitle());
            pijo.put("bizNo", hi.getBizNo());
            pijo.put("bpdName", hi.getBpdName());
            pijo.put("createTime", DateUtil.formatDate(hi.getCreateTime(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
            pijo.put("dueTime", DateUtil.formatDate(hi.getDueTime(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
            pijo.put("completeDate", DateUtil.formatDate(hi.getCompleteDate(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));

            paramMap.put("piId", hi.getPiId());
            paramMap.put("status", "hi");
        } else {
            PPi pi = dao.selectOne(Mapper.PPiMapper, "selectByPrimaryKey", piEid);
            bpdId = pi.getBpdId();
            versionId = pi.getVersionid();
            pijo.put("piEid", AES.encrypt(pi.getPiEid()));
            pijo.put("piId", AES.encrypt(pi.getPiId()));
            pijo.put("bpdId", pi.getBpdId());
            pijo.put("versionid", pi.getVersionid());
            pijo.put("status", pi.getStatus());
            pijo.put("title", pi.getTitle());
            pijo.put("bizNo", pi.getBizNo());
            pijo.put("bpdName", pi.getBpdName());
            pijo.put("createTime", DateUtil.formatDate(pi.getCreateTime(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
            pijo.put("dueTime", DateUtil.formatDate(pi.getDueTime(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));

            paramMap.put("piId", pi.getPiId());
            paramMap.put("status", "pi");
        }

        //get start task
        PTaskDone done = dao.selectOne(Mapper.PTaskDoneMapper, "selectStartTask", paramMap);
        JSONObject tijo = new JSONObject();
        tijo.put("activityName", done.getActivityName());
        tijo.put("priority", done.getPriority());
        tijo.put("createTime", DateUtil.formatDate(done.getCreateTime(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
        tijo.put("receiveTime", DateUtil.formatDate(done.getReceiveTime(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
        tijo.put("dueTime", DateUtil.formatDate(done.getDueTime(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));
        tijo.put("completeDate", DateUtil.formatDate(done.getCompleteDate(), DateUtil.DATEFORMATMM_ZH, timezoneOffset));

        rtn.put("pi", pijo);
        rtn.put("ti", tijo);

        //查询version
        JSONObject version = bvcs.getVersionJson(tenantId, bpdId, versionId);
        version.remove(EngineConst.BPMN);   //remove bpmn for performance issue
        //activityConf
        JSONObject formBinding = version.getJSONObject(EngineConst.BPMNCONF).getJSONObject("Collaboration_1").getJSONObject("viewFormBinding");
        //form
        rtn.put("formBinding", formBinding);

        //data in main table
        rtn.put("datam", getDataM(tenantId, piEid));

        return rtn;
    }

    public JSONObject markRead(String tenantId, String tiId) {
        JSONObject rtn = new JSONObject();
        PTaskTodo todo = new PTaskTodo();
        if (tenantId!=null && StringUtils.isNumeric(tenantId)) {
            todo.setTenantId(Integer.parseInt(tenantId));
        }
        todo.setTiId(tiId);
        todo.setReceiveTime(DateUtil.getGMTDate());
        todo.setStatus(PTaskTodo.STATUS_READ);
        int rs = dao.update(Mapper.PTaskTodoMapper, "updateByPrimaryKeySelective", todo);
        rtn.put(Const.AJAX_RESULT, rs);
        return rtn;
    }

    public JSONArray getDonesByPiId(String tenantId, String piId, String lang, int timezoneOffset) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        if (tenantId!=null && StringUtils.isNumeric(tenantId)) {
            paramMap.put(Const.TENANT_ID, tenantId);
        }
        paramMap.put("piId", piId);
        List<Map<String, Object>> list = dao.selectList(Mapper.TaskQueryMapper, "getDonesByPiId", paramMap);
        JSONArray rows = new JSONArray();
        int no = 0;
        if (list!=null && list.size()>0) {
            for (Map<String, Object> obj : list) {
                JSONObject node = DhxUtil.toJsonWithDateAli(obj, lang, timezoneOffset, true);
                node.put("_ITEM_NO", ++no);
                if (node.containsKey("tiId")) {
                    node.put("tiId", AES.encrypt(node.getString("tiId")));
                }
                if (node.containsKey("piEid")) {
                    node.put("piEid", AES.encrypt(node.getString("piEid")));
                }
                rows.add(node);
            }
        }
        return rows;
    }

    /**
     * 获取主表单数据
     * @param tenantId
     * @param piEid
     * @return
     */
    private JSONObject getDataM(String tenantId, String piEid) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        if (tenantId!=null && StringUtils.isNumeric(tenantId)) {
            paramMap.put(Const.TENANT_ID, tenantId);
        }
        paramMap.put("piEid", piEid);
        List<PDataM> entries = dao.selectList(Mapper.PDataMMapper, "selectByPiEid", paramMap);
        JSONObject rtn = new JSONObject();
        for (PDataM entry : entries) {
            rtn.put(entry.getModel().toUpperCase(), JSONObject.parse(entry.getBizData()));
        }
        return rtn;
    }

    /**
     * 获取主表单数据
     * @param tenantId
     * @param piEid
     * @return
     */
    public int saveDataM(String tenantId, String piEid, String datam) {
        List<PDataM> entries = new ArrayList<PDataM>();
        JSONObject datamJo = JSONObject.parseObject(datam);
        for (String model : datamJo.keySet()) {
            PDataM m = new PDataM();
            if (tenantId!=null && StringUtils.isNumeric(tenantId)) {
                m.setTenantId(Integer.parseInt(tenantId));
            }
            m.setPiEid(piEid);
            m.setModel(model);
            m.setBizData(datamJo.getJSONObject(model).toJSONString());
            entries.add(m);
        }
        int rs = dao.batchInsert(Mapper.PDataMMapper, "insertOrReplace", entries);
        return rs;
    }

    /**
     * 获取子表单数据
     * @param tenantId
     * @param piEid
     * @param model
     * @param lang
     * @param order
     * @param sort
     * @param offset
     * @param limit
     * @param timezoneOffset
     * @param search
     * @return
     */
    public JSONObject getDataS(String tenantId,
                                String piEid,
                                String model,
                                String lang,
                                String order,
                                String sort,
                                int offset,
                                int limit,
                                int timezoneOffset,
                                String search) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        if (tenantId!=null && StringUtils.isNumeric(tenantId)) {
            paramMap.put(Const.TENANT_ID, tenantId);
        }
        paramMap.put("piEid", piEid);
        paramMap.put("model", model);
        paramMap.put("order", order);
        paramMap.put("sort", sort);
        paramMap.put("search", search);

        PageHelper.offsetPage(offset, limit);
        List<PDataS> entries = dao.selectList(Mapper.PDataSMapper, "selectByPiEid", paramMap);
        PageInfo pageInfo = new PageInfo(entries);

        JSONObject rtn = new JSONObject();
        JSONArray rows = DhxUtil.toJsonWithDate(entries, lang, timezoneOffset);
        if (rows!=null && rows.size()>0) {
            for (int i=0; i<rows.size(); i++) {
                rows.getJSONObject(i).remove(Const.TENANT_ID);
                rows.getJSONObject(i).remove("piEid");
            }
        }
        rtn.put(DhxUtil.ROWS, rows);
        rtn.put(DhxUtil.TOTAL_COUNT, pageInfo.getTotal());
        return rtn;
    }
}
